#include "SPI.h"
#include <stm32f10x.h>

void SPI_init() {

    RCC_APB2PeriphClockCmd(SPI_BUS, ENABLE);

    GPIO_InitTypeDef GPIOA_initial;

    GPIOA_initial.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIOA_initial.GPIO_Pin = SPI_NSS | SPI_SCK | SPI_MOSI;
    GPIOA_initial.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(SPI_PORT, &GPIOA_initial);

    GPIOA_initial.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIOA_initial.GPIO_Pin = SPI_MISO;
    // GPIOA_initial.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(SPI_PORT, &GPIOA_initial);

    // SPI mode 1
    // SCLK low level
    GPIO_WriteBit(SPI_PORT, SPI_SCK, Bit_RESET);
    // not selected,low level effect
    GPIO_WriteBit(SPI_PORT, SPI_NSS, Bit_SET);
}

static void SPI_NSS_out_bit(byte bit) {
    if (bit) {
        GPIO_WriteBit(SPI_PORT, SPI_NSS, Bit_SET);
    } else {
        GPIO_WriteBit(SPI_PORT, SPI_NSS, Bit_RESET);
    }
}
static void SPI_SCK_out_bit(byte bit) {
    if (bit) {
        GPIO_WriteBit(SPI_PORT, SPI_SCK, Bit_SET);
    } else {
        GPIO_WriteBit(SPI_PORT, SPI_SCK, Bit_RESET);
    }
}
static void SPI_MOSI_out_bit(byte bit) {
    if (bit) {
        GPIO_WriteBit(SPI_PORT, SPI_MOSI, Bit_SET);
    } else {
        GPIO_WriteBit(SPI_PORT, SPI_MOSI, Bit_RESET);
    }
}
static byte SPI_MISO_in_bit() {

    return GPIO_ReadInputDataBit(SPI_PORT, SPI_MISO);
}

// mode 1
void SPI_spare_status() {

    // reset to spare status output
    SPI_NSS_out_bit(1);
    SPI_SCK_out_bit(0);
}

// mode 1,according to flash SPI mode
// MOSI SCK低电平改变值，高电平不变值 Master write
// MISO SCK低电平值不变，高电平改变值 slave write
void SPI_rw(byte rd[], int rd_len, byte wd[], int wd_len) {

    // you first silence
    SPI_spare_status();
    // cs start,low level available
    // selected
    SPI_NSS_out_bit(0);
    for (int i = 0; i < wd_len; i++) {
        // p();
        // p_i(wd[i]);
        // MSB,most positon output first
        for (int j = 7; j >= 0; j--) {
            // p();
            // p_i(wd[i] >> j & 1);
            SPI_SCK_out_bit(0);

            SPI_MOSI_out_bit(wd[i] >> j & 1);

            SPI_SCK_out_bit(1);
        }
    }

    for (int i = 0; i < rd_len; i++) {
        for (int j = 7; j >= 0; j--) {
            // 必须变由高电平变为低电平 才能取到值
            SPI_SCK_out_bit(1);
            SPI_SCK_out_bit(0);

            byte rbit = SPI_MISO_in_bit();
            if (rbit == 1) {
                rd[i] |= rbit << j;
            } else {
                rd[i] &= ~(1 << j); // 保证不用提前清空rd的数据为0
            }
        }
        // p();
        // p_i(rd[i]);
    }

    // back to first state,spare status
    // not selected
    // end to first silence
    SPI_spare_status();
}
